#include "screen.h"
#include "x86.h"
#include "font.h"

void init_screen(boot_info_t *boot_ptr)
{
    boot_ptr->vram = (int8_t *)VRAM;
    boot_ptr->color_mode = 8;
    boot_ptr->x_size = 320;
    boot_ptr->y_size = 200;
}

void clear_screen(uint8_t color) // 15:pure white
{
    uint8_t *p = (uint8_t *)VRAM;

    for (int i = 0; i <= 0xffff; i++)
    {
        p[i] = color;
    }
}

/**
 * @brief 设置调色板，  只用到了16个color,后面的都没有用到。
 *
 * @param start rgb数组起始位置
 * @param end rgb数组结束位置
 * @param rgb 颜色数组指针
 * @note end-start最大值为rgb数组大小/3，请注意不要大于该值，可能会出现内存泄漏
 */
static void set_palette(uint8_t start, uint8_t end, uint8_t *rgb)
{
    uint32_t eflag = read_eflags(); //记录从前的cpsr值

    io_cli(); // disable interrupt

    outb(0x03c8, start);
    for (uint8_t i = start; i <= end; i++)
    {
        outb(0x03c9, *(rgb) / 4); // outb函数是往指定的设备，送数据。
        outb(0x03c9, *(rgb + 1) / 4);
        outb(0x03c9, *(rgb + 2) / 4);
        rgb = rgb + 3;
    }

    write_eflags(eflag); //恢复从前的cpsr
    return;
}

//初始化调色板，table_rgb[]保存了16种color的编码。
//什么调色板是这样进行设置，这个与x86的port 0x03c8 0x03c9
void init_palette(void)
{
    // 16种color，每个color三个字节。
    uint8_t table_rgb[16 * 3] = {
        0x00, 0x00, 0x00, /*0:black*/
        0xff, 0x00, 0x00, /*1:light red*/
        0x00, 0xff, 0x00, /*2:light green*/
        0xff, 0xff, 0x00, /*3:light yellow*/

        0x00, 0x00, 0xff, /*4:light blue*/
        0xff, 0x00, 0xff, /*5:light purper*/
        0x00, 0xff, 0xff, /*6:light blue*/
        0xff, 0xff, 0xff, /*7:white*/

        0xc6, 0xc6, 0xc6, /*8:light gray*/
        0x84, 0x00, 0x00, /*9:dark red*/
        0x00, 0x84, 0x00, /*10:dark green*/
        0x84, 0x84, 0x00, /*11:dark yellow*/

        0x00, 0x00, 0x84, /*12:dark 青*/
        0x84, 0x00, 0x84, /*13:dark purper*/
        0x00, 0x84, 0x84, /*14:light blue*/
        0x84, 0x84, 0x84, /*15:dark gray*/
    };

    set_palette(0, 15, table_rgb);
}

static void box_fill8(uint8_t *vram, int32_t xsize, uint8_t color, int32_t x0, int32_t y0, int32_t x1, int32_t y1)
{
    int32_t x, y;
    for (y = y0; y <= y1; y++)
    {
        for (x = x0; x <= x1; x++)
        {
            vram[y * xsize + x] = color;
        }
    }
}

void box_fill(uint8_t color, int32_t x0, int32_t y0, int32_t x1, int32_t y1)
{
    box_fill8((uint8_t *)VRAM, 320, color, x0, y0, x1, y1);
}

void draw_window(void)
{
    int32_t x = 320, y = 200;

    // draw a window
    box_fill(7, 0, 0, x - 1, y - 29);
    // task button
    box_fill(8, 0, y - 28, x - 1, y - 28);
    box_fill(7, 0, y - 27, x - 1, y - 27);
    box_fill(8, 0, y - 26, x - 1, y - 1);

    // left button
    box_fill(7, 3, y - 24, 59, y - 24);
    box_fill(7, 2, y - 24, 2, y - 4);
    box_fill(15, 3, y - 4, 59, y - 4);
    box_fill(15, 59, y - 23, 59, y - 5);
    box_fill(0, 2, y - 3, 59, y - 3);
    box_fill(0, 60, y - 24, 60, y - 3);

    // right button
    box_fill(15, x - 47, y - 24, x - 4, y - 24);
    box_fill(15, x - 47, y - 23, x - 47, y - 4);
    box_fill(7, x - 47, y - 3, x - 4, y - 3);
    box_fill(7, x - 3, y - 24, x - 3, y - 3);
}

///关于mouse的函数
void init_mouse(int8_t *mouse, int8_t bg)
{
#define background 7
#define outline 0
#define inside 2

    const static int8_t cursor[16][16] = {
        "**************..",
        "*OOOOOOOOOOO*...",
        "*OOOOOOOOOO*....",
        "*OOOOOOOOO*.....",
        "*OOOOOOOO*......",
        "*OOOOOOO*.......",
        "*OOOOOOO*.......",
        "*OOOOOOOO*......",
        "*OOOO**OOO*.....",
        "*OOO*..*OOO*....",
        "*OO*....*OOO*...",
        "*O*......*OOO*..",
        "**........*OOO*.",
        "*..........*OOO*",
        "............*OO*",
        ".............***"};

    uint8_t x, y;
    for (y = 0; y < 16; y++)
    {
        for (x = 0; x < 16; x++)
        {
            switch (cursor[y][x])
            {
            case '.':
                mouse[x + 16 * y] = bg;
                break; // background
            case '*':
                mouse[x + 16 * y] = outline;
                break; // outline
            case 'O':
                mouse[x + 16 * y] = inside;
                break; // inside
            }
        }
    }
}

void display_mouse(int8_t *vram, int32_t xsize, int32_t pxsize, int32_t pysize, int32_t px0, int32_t py0, int8_t *buf, int32_t bxsize)
{
    int32_t x, y;
    for (y = 0; y < pysize; y++)
    {
        for (x = 0; x < pxsize; x++)
        {
            vram[(py0 + y) * xsize + (px0 + x)] = buf[y * bxsize + x];
        }
    }
}

/*     value     color
       0         black
       10        light green
       20	     dark gray
       30        white
       40        red
       50	     a litter dark green
       60        pink red
       70        yello+green
       80        purper
       90        orange
       100       light blue
       110       dark red
       120       dark green
       130	     dark purper
       140       dark orange
       150	     dark blue
       160       dark red+gray
       170       dark green+gray
       180	     dark zhu red


*/
